#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/epoll.h>
#include <string.h>
#include <string>
#include <thread>
#include <atomic>
#include <chrono>
#include <iomanip>
#include <queue>
#include <mutex>

/**
 * 修复版 Epoll 客户端类
 * 
 * 修复的问题：
 * 1. 连接持久化 - 避免发送消息后立即断开
 * 2. 连接状态管理 - 更好的连接状态跟踪
 * 3. 错误处理 - 改进错误恢复机制
 * 4. 消息发送 - 确保消息能够正确发送
 */
class FixedEpollClient {
private:
    int client_fd;                    // 客户端套接字
    int epoll_fd;                     // epoll 实例文件描述符
    std::string server_ip;            // 服务器 IP 地址
    int server_port;                  // 服务器端口
    std::atomic<bool> running;        // 客户端运行状态
    std::atomic<bool> connected;      // 连接状态
    std::atomic<int> message_count;   // 消息计数器
    
    // 消息队列相关
    std::queue<std::string> send_queue;  // 发送消息队列
    std::mutex queue_mutex;              // 队列互斥锁
    
    // 常量定义
    static const int MAX_EVENTS = 10;     // epoll 最大事件数
    static const int BUFFER_SIZE = 1024;  // 缓冲区大小

public:
    /**
     * 构造函数
     * @param ip 服务器 IP 地址
     * @param port 服务器端口
     */
    FixedEpollClient(const std::string& ip, int port) 
        : server_ip(ip), server_port(port), client_fd(-1), epoll_fd(-1), 
          running(false), connected(false), message_count(0) {
        
        std::cout << "=== 修复版 Epoll 客户端初始化 ===" << std::endl;
        std::cout << "目标服务器: " << server_ip << ":" << server_port << std::endl;
        std::cout << "最大事件数: " << MAX_EVENTS << std::endl;
        std::cout << "缓冲区大小: " << BUFFER_SIZE << " 字节" << std::endl;
        std::cout << "=================================" << std::endl;
    }

    /**
     * 析构函数 - 清理资源
     */
    ~FixedEpollClient() {
        std::cout << "\n=== 客户端关闭，清理资源 ===" << std::endl;
        if (client_fd != -1) {
            close(client_fd);
            std::cout << "✓ 关闭客户端套接字" << std::endl;
        }
        if (epoll_fd != -1) {
            close(epoll_fd);
            std::cout << "✓ 关闭 epoll 实例" << std::endl;
        }
        std::cout << "✓ 资源清理完成" << std::endl;
    }

    /**
     * 设置文件描述符为非阻塞模式
     * @param fd 文件描述符
     * @return 成功返回 true，失败返回 false
     */
    bool setNonBlocking(int fd) {
        int flags = fcntl(fd, F_GETFL, 0);
        if (flags == -1) {
            std::cerr << "❌ 获取文件描述符标志失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
            std::cerr << "❌ 设置非阻塞模式失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        return true;
    }

    /**
     * 将文件描述符添加到 epoll 监听列表
     * @param fd 文件描述符
     * @param events 监听的事件类型
     * @return 成功返回 true，失败返回 false
     */
    bool addToEpoll(int fd, uint32_t events) {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = fd;
        
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
            std::cerr << "❌ 添加文件描述符到 epoll 失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        return true;
    }

    /**
     * 修改 epoll 监听事件
     * @param fd 文件描述符
     * @param events 新的事件类型
     * @return 成功返回 true，失败返回 false
     */
    bool modifyEpoll(int fd, uint32_t events) {
        struct epoll_event ev;
        ev.events = events;
        ev.data.fd = fd;
        
        if (epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ev) == -1) {
            std::cerr << "❌ 修改 epoll 事件失败: " << strerror(errno) << std::endl;
            return false;
        }
        
        return true;
    }

    /**
     * 获取当前时间戳（用于日志）
     * @return 格式化的时间字符串
     */
    std::string getTimestamp() {
        auto now = std::chrono::system_clock::now();
        auto time_t = std::chrono::system_clock::to_time_t(now);
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            now.time_since_epoch()) % 1000;
        
        std::stringstream ss;
        ss << std::put_time(std::localtime(&time_t), "%H:%M:%S");
        ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
        return ss.str();
    }

    /**
     * 初始化客户端
     * @return 成功返回 true，失败返回 false
     */
    bool init() {
        std::cout << "\n=== 开始初始化客户端 ===" << std::endl;
        
        // 步骤 1: 创建 TCP 套接字
        std::cout << "1. 创建 TCP 套接字..." << std::endl;
        client_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (client_fd == -1) {
            std::cerr << "❌ 创建套接字失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ 套接字创建成功，文件描述符: " << client_fd << std::endl;

        // 步骤 2: 设置非阻塞模式
        std::cout << "2. 设置非阻塞模式..." << std::endl;
        if (!setNonBlocking(client_fd)) {
            std::cerr << "❌ 设置非阻塞模式失败" << std::endl;
            return false;
        }
        std::cout << "✓ 非阻塞模式设置成功" << std::endl;

        // 步骤 3: 创建 epoll 实例
        std::cout << "3. 创建 epoll 实例..." << std::endl;
        epoll_fd = epoll_create1(0);
        if (epoll_fd == -1) {
            std::cerr << "❌ 创建 epoll 实例失败: " << strerror(errno) << std::endl;
            return false;
        }
        std::cout << "✓ epoll 实例创建成功，文件描述符: " << epoll_fd << std::endl;

        // 步骤 4: 准备连接参数
        std::cout << "4. 准备连接参数..." << std::endl;
        struct sockaddr_in server_addr;
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(server_port);
        
        if (inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr) <= 0) {
            std::cerr << "❌ 无效的 IP 地址: " << server_ip << std::endl;
            return false;
        }
        std::cout << "✓ 连接参数准备完成" << std::endl;

        std::cout << "=== 客户端初始化完成 ===" << std::endl;
        return true;
    }

    /**
     * 连接到服务器
     * @return 成功返回 true，失败返回 false
     */
    bool connectToServer() {
        std::cout << "\n=== 开始连接服务器 ===" << std::endl;
        std::cout << "目标地址: " << server_ip << ":" << server_port << std::endl;
        
        // 准备服务器地址
        struct sockaddr_in server_addr;
        memset(&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(server_port);
        inet_pton(AF_INET, server_ip.c_str(), &server_addr.sin_addr);

        // 发起非阻塞连接
        std::cout << "1. 发起连接请求..." << std::endl;
        if (connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
            if (errno != EINPROGRESS) {
                std::cerr << "❌ 连接失败: " << strerror(errno) << std::endl;
                return false;
            }
            std::cout << "✓ 连接请求已发送，等待响应..." << std::endl;
        } else {
            std::cout << "✓ 连接立即成功" << std::endl;
            connected = true;
        }

        // 将套接字添加到 epoll（监听连接状态和可读事件）
        std::cout << "2. 注册套接字到 epoll..." << std::endl;
        if (!addToEpoll(client_fd, EPOLLIN | EPOLLOUT)) {
            std::cerr << "❌ 注册套接字失败" << std::endl;
            return false;
        }
        std::cout << "✓ 套接字注册成功" << std::endl;

        return true;
    }

    /**
     * 处理连接状态
     * 检查非阻塞连接是否完成
     */
    void handleConnect() {
        int error = 0;
        socklen_t len = sizeof(error);
        
        if (getsockopt(client_fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
            std::cerr << "[" << getTimestamp() << "] ❌ 获取连接状态失败: " << strerror(errno) << std::endl;
            connected = false;
            return;
        }

        if (error != 0) {
            std::cerr << "[" << getTimestamp() << "] ❌ 连接失败: " << strerror(error) << std::endl;
            connected = false;
            return;
        }

        // 连接成功
        connected = true;
        std::cout << "[" << getTimestamp() << "] 🎉 连接服务器成功!" << std::endl;
        std::cout << "   服务器地址: " << server_ip << ":" << server_port << std::endl;
        std::cout << "   本地文件描述符: " << client_fd << std::endl;
        
        // 连接成功后，移除 EPOLLOUT 事件，只监听可读事件
        if (!modifyEpoll(client_fd, EPOLLIN)) {
            std::cerr << "[" << getTimestamp() << "] ⚠️  修改 epoll 事件失败" << std::endl;
        }
    }

    /**
     * 处理接收到的数据
     */
    void handleReceive() {
        char buffer[BUFFER_SIZE];
        ssize_t bytes_read = recv(client_fd, buffer, BUFFER_SIZE - 1, 0);
        
        if (bytes_read > 0) {
            buffer[bytes_read] = '\0';
            std::cout << "[" << getTimestamp() << "] 📨 收到服务器消息: " << buffer;
        } else if (bytes_read == 0) {
            // 服务器断开连接
            std::cout << "[" << getTimestamp() << "] 👋 服务器断开连接" << std::endl;
            connected = false;
        } else if (bytes_read == -1) {
            if (errno != EAGAIN && errno != EWOULDBLOCK) {
                std::cerr << "[" << getTimestamp() << "] ❌ 接收数据时发生错误: " << strerror(errno) << std::endl;
                connected = false;
            }
        }
    }

    /**
     * 发送消息 - 修复版本
     * 
     * 修复的问题：
     * 1. 确保连接状态检查
     * 2. 改进错误处理
     * 3. 避免发送后立即断开
     * 
     * @param message 要发送的消息
     * @return 成功返回 true，失败返回 false
     */
    bool sendMessage(const std::string& message) {
        if (!connected) {
            std::cerr << "[" << getTimestamp() << "] ❌ 未连接到服务器，无法发送消息" << std::endl;
            return false;
        }

        ssize_t bytes_sent = send(client_fd, message.c_str(), message.length(), 0);
        if (bytes_sent > 0) {
            message_count++;
            std::cout << "[" << getTimestamp() << "] 📤 消息发送成功 (" << bytes_sent << " 字节)" << std::endl;
            std::cout << "   消息内容: " << message;
            std::cout << "   累计发送: " << message_count.load() << " 条消息" << std::endl;
            return true;
        } else if (bytes_sent == -1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                // 发送缓冲区满，将消息加入队列
                std::lock_guard<std::mutex> lock(queue_mutex);
                send_queue.push(message);
                std::cout << "[" << getTimestamp() << "] ⏳ 发送缓冲区满，消息已加入队列" << std::endl;
                return true;
            } else {
                std::cerr << "[" << getTimestamp() << "] ❌ 发送消息失败: " << strerror(errno) << std::endl;
                return false;
            }
        }
        return false;
    }

    /**
     * 处理发送队列
     * 尝试发送队列中的消息
     */
    void processSendQueue() {
        std::lock_guard<std::mutex> lock(queue_mutex);
        while (!send_queue.empty()) {
            std::string message = send_queue.front();
            ssize_t bytes_sent = send(client_fd, message.c_str(), message.length(), 0);
            
            if (bytes_sent > 0) {
                send_queue.pop();
                message_count++;
                std::cout << "[" << getTimestamp() << "] 📤 队列消息发送成功 (" << bytes_sent << " 字节)" << std::endl;
            } else if (bytes_sent == -1) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    // 发送缓冲区仍然满，停止处理
                    break;
                } else {
                    std::cerr << "[" << getTimestamp() << "] ❌ 发送队列消息失败: " << strerror(errno) << std::endl;
                    break;
                }
            }
        }
    }

    /**
     * 用户输入处理线程 - 修复版本
     * 
     * 修复的问题：
     * 1. 保持连接状态
     * 2. 改进用户交互
     * 3. 避免意外断开
     */
    void inputThread() {
        std::cout << "\n=== 用户输入线程启动 ===" << std::endl;
        std::cout << "💡 使用说明:" << std::endl;
        std::cout << "  - 输入消息并按回车发送" << std::endl;
        std::cout << "  - 输入 'quit' 或 'exit' 退出程序" << std::endl;
        std::cout << "  - 输入 'status' 查看连接状态" << std::endl;
        std::cout << "  - 输入 'help' 显示帮助信息" << std::endl;
        std::cout << "  - 输入 'clear' 清屏" << std::endl;
        std::cout << "===============================" << std::endl;

        std::string input;
        while (running) {
            std::getline(std::cin, input);
            if (!running) break;
            
            if (!input.empty()) {
                if (input == "quit" || input == "exit") {
                    std::cout << "[" << getTimestamp() << "] 🛑 收到退出命令" << std::endl;
                    running = false;
                    break;
                } else if (input == "status") {
                    showStatus();
                } else if (input == "help") {
                    showHelp();
                } else if (input == "clear") {
                    system("clear");
                    std::cout << "[" << getTimestamp() << "] 🧹 屏幕已清空" << std::endl;
                } else {
                    // 发送消息 - 修复：确保连接状态
                    if (connected) {
                        if (!sendMessage(input + "\n")) {
                            std::cerr << "[" << getTimestamp() << "] ❌ 消息发送失败" << std::endl;
                        }
                    } else {
                        std::cerr << "[" << getTimestamp() << "] ❌ 未连接到服务器，请等待连接..." << std::endl;
                    }
                }
            }
        }
        
        std::cout << "[" << getTimestamp() << "] 👋 用户输入线程结束" << std::endl;
    }

    /**
     * 显示连接状态
     */
    void showStatus() {
        std::cout << "\n[" << getTimestamp() << "] 📊 客户端状态:" << std::endl;
        std::cout << "   连接状态: " << (connected ? "✅ 已连接" : "❌ 未连接") << std::endl;
        std::cout << "   服务器地址: " << server_ip << ":" << server_port << std::endl;
        std::cout << "   文件描述符: " << client_fd << std::endl;
        std::cout << "   累计发送消息: " << message_count.load() << " 条" << std::endl;
        
        std::lock_guard<std::mutex> lock(queue_mutex);
        std::cout << "   发送队列长度: " << send_queue.size() << " 条" << std::endl;
        std::cout << "   =================================" << std::endl;
    }

    /**
     * 显示帮助信息
     */
    void showHelp() {
        std::cout << "\n[" << getTimestamp() << "] 📖 帮助信息:" << std::endl;
        std::cout << "   命令列表:" << std::endl;
        std::cout << "     quit/exit  - 退出程序" << std::endl;
        std::cout << "     status     - 显示连接状态" << std::endl;
        std::cout << "     help       - 显示此帮助信息" << std::endl;
        std::cout << "     clear      - 清屏" << std::endl;
        std::cout << "   其他输入将作为消息发送给服务器" << std::endl;
        std::cout << "   =================================" << std::endl;
    }

    /**
     * 统计信息线程
     * 定期输出客户端运行状态
     */
    void statsThread() {
        while (running) {
            std::this_thread::sleep_for(std::chrono::seconds(60));  // 每60秒输出一次统计
            if (running) {
                std::cout << "\n[" << getTimestamp() << "] 📈 客户端运行统计:" << std::endl;
                std::cout << "   连接状态: " << (connected ? "已连接" : "未连接") << std::endl;
                std::cout << "   累计发送消息: " << message_count.load() << " 条" << std::endl;
                std::cout << "   运行时间: 持续运行中..." << std::endl;
                std::cout << "   =================================" << std::endl;
            }
        }
    }

    /**
     * 运行客户端主循环 - 修复版本
     * 
     * 修复的问题：
     * 1. 改进事件处理逻辑
     * 2. 更好的连接状态管理
     * 3. 避免意外断开连接
     */
    void run() {
        struct epoll_event events[MAX_EVENTS];
        running = true;
        
        std::cout << "\n=== 客户端启动，开始运行 ===" << std::endl;
        
        // 启动用户输入线程
        std::thread input_thread(&FixedEpollClient::inputThread, this);
        
        // 启动统计线程
        std::thread stats_thread(&FixedEpollClient::statsThread, this);
        
        // 连接服务器
        if (!connectToServer()) {
            std::cerr << "❌ 连接服务器失败" << std::endl;
            running = false;
        }
        
        // 主事件循环
        while (running) {
            int num_events = epoll_wait(epoll_fd, events, MAX_EVENTS, 100); // 100ms 超时
            if (num_events == -1) {
                if (errno == EINTR) {
                    // 被信号中断，继续循环
                    continue;
                }
                std::cerr << "[" << getTimestamp() << "] ❌ epoll_wait 失败: " << strerror(errno) << std::endl;
                break;
            }

            // 处理所有就绪的事件
            for (int i = 0; i < num_events; ++i) {
                if (events[i].events & EPOLLOUT && !connected) {
                    // 连接完成事件
                    handleConnect();
                }
                
                if (events[i].events & EPOLLIN) {
                    // 可读事件
                    handleReceive();
                }
                
                if (events[i].events & EPOLLERR) {
                    // 错误事件
                    std::cerr << "[" << getTimestamp() << "] ❌ 套接字发生错误" << std::endl;
                    connected = false;
                }
                
                if (events[i].events & EPOLLHUP) {
                    // 挂起事件（连接断开）
                    std::cout << "[" << getTimestamp() << "] 🔌 连接挂起" << std::endl;
                    connected = false;
                }
            }
            
            // 处理发送队列
            if (connected) {
                processSendQueue();
            }
        }
        
        // 等待线程结束
        if (input_thread.joinable()) {
            input_thread.join();
        }
        if (stats_thread.joinable()) {
            stats_thread.join();
        }
        
        std::cout << "\n=== 客户端主循环结束 ===" << std::endl;
    }

    /**
     * 优雅关闭客户端
     */
    void shutdown() {
        std::cout << "\n[" << getTimestamp() << "] 🛑 收到关闭信号，开始优雅关闭..." << std::endl;
        running = false;
    }
};

/**
 * 主函数
 */
int main(int argc, char* argv[]) {
    std::cout << "🚀 修复版 Epoll 客户端启动" << std::endl;
    std::cout << "版本: 2.1 (修复版)" << std::endl;
    std::cout << "作者: AI Assistant" << std::endl;
    std::cout << "功能: 高性能多线程网络通信客户端" << std::endl;
    std::cout << "修复: 连接持久化和消息发送问题" << std::endl;
    
    // 解析命令行参数
    std::string server_ip = "127.0.0.1";
    int server_port = 8888;
    
    if (argc > 1) {
        server_ip = argv[1];
    }
    if (argc > 2) {
        server_port = atoi(argv[2]);
        if (server_port <= 0 || server_port > 65535) {
            std::cerr << "❌ 无效的端口号: " << argv[2] << std::endl;
            std::cerr << "端口号必须在 1-65535 范围内" << std::endl;
            return 1;
        }
    }

    std::cout << "\n📋 启动参数:" << std::endl;
    std::cout << "服务器地址: " << server_ip << ":" << server_port << std::endl;
    std::cout << "使用方法: " << argv[0] << " [服务器IP] [服务器端口]" << std::endl;
    std::cout << "示例: " << argv[0] << " 192.168.1.100 9999" << std::endl;

    // 创建客户端实例
    FixedEpollClient client(server_ip, server_port);
    
    // 初始化客户端
    if (!client.init()) {
        std::cerr << "\n❌ 客户端初始化失败，程序退出" << std::endl;
        return 1;
    }

    // 运行客户端
    try {
        client.run();
    } catch (const std::exception& e) {
        std::cerr << "\n❌ 客户端运行时发生异常: " << e.what() << std::endl;
        return 1;
    } catch (...) {
        std::cerr << "\n❌ 客户端运行时发生未知异常" << std::endl;
        return 1;
    }
    
    std::cout << "\n✅ 客户端正常退出" << std::endl;
    return 0;
}